package edu.manju.mimi.core.security;

import com.alibaba.fastjson2.JSON;
import edu.manju.mimi.core.R;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

/**
 * <h4>mimi-core</h4>
 * <p>拦截器： 拦截需要Token才能访问的方法</p>
 *
 * @author : Lebei(lebei163@163.com)
 * @date : 2023-02-24 20:55
 **/
@Component
public class LoginInterceptor implements HandlerInterceptor {
    public final static String CURRENT_USER = "CURRENT_USER";

    @Autowired
    private JwtService jwtService;

    @Autowired
    private RedisService redisService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 非处理器方法
        if (!(handler instanceof HandlerMethod handlerMethod)) {
            return true;
        }

        // 无需授权的方法
        if (!handlerMethod.hasMethodAnnotation(NeedAuth.class)) {
            return true;
        }

        String token = jwtService.getToken(request);
        if (token == null) {
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write(JSON.toJSONString(R.fail(501, "No token available!")));
            return false;
        }

        // Token验证未通过
        boolean verify = jwtService.verify(token);
        if (!verify) {
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write(JSON.toJSONString(R.fail(501, "Token was invalid!")));
            return false;
        }

        // Token已过期
        boolean expired = jwtService.isExpire(token);
        if (expired) {
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write(JSON.toJSONString(R.fail(501, "Token was expired!")));
            return false;
        }

        // Token未在数据库中
        Integer userId = null;
        try {
            // @see LoginController#login
            userId = Integer.valueOf(redisService.get(token));
        } catch (NumberFormatException e) {
        }

        if (userId == null) {
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write(JSON.toJSONString(R.fail(501, "Token was not in Redis!")));
            return false;
        }

        // @see LoginUserIdResolver#resolveArgument
        request.setAttribute(CURRENT_USER, userId);

        return true;
    }
}
